package com.kedacom.ctsp.authz.security;

import com.kedacom.ctsp.authz.AuthenticationSupplier;
import com.kedacom.ctsp.authz.access.*;
import com.kedacom.ctsp.authz.security.controller.AuthorizationController;
import com.kedacom.ctsp.authz.security.provider.*;
import com.kedacom.ctsp.serialize.ISerialization;
import com.kedacom.ctsp.serialize.support.java.CompactedJavaSerialization;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

/**
 * Spring Security的自动化配置类
 *
 * @author xuwei
 * @create 2017-11-28 18:44
 **/
@Configuration
@EnableWebSecurity
@ComponentScan
@Slf4j
public class AuthzSecurityAutoConfiguration {

    @Bean
    public AuthenticationSupplier authenticationSupplier() {
        return () -> {
            if (SecurityContextHolder.getContext().getAuthentication() == null) {
                return null;
            }
            Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            if (principal == null) {
                return null;
            }
            if (principal instanceof AuthUserDetails) {
                return ((AuthUserDetails) principal).getAuthentication();
            } else {
                return null;
            }
        };
    }

    @Bean
    @ConditionalOnMissingBean
    protected AuthorizationController authorizationController() {
        return new AuthorizationController();
    }

    @Bean
    @ConditionalOnMissingBean
    protected SessionRegistry sessionRegistry() {
        return new MemorySessionRegistryImpl();
    }

    @Bean
    @ConditionalOnMissingBean
    protected TokenManager tokenManager() {
        return new MemoryTokenManager();
    }

    @Bean
    @ConditionalOnMissingBean
    protected ISerialization serialization() {
        return new CompactedJavaSerialization();
    }

    /**
     * @return 登录成功后的自定义处理（不再由SpringSecurity自动跳转页面）
     */
    @Bean
    @ConditionalOnMissingBean(AuthenticationSuccessHandler.class)
    public RestAuthenticationSuccessHandler restAuthenticationSuccessHandler() {
        return new RestAuthenticationSuccessHandler();
    }

    /**
     * @return 登录失败后的自定义处理（不再由SpringSecurity自动跳转页面）
     */
    @Bean
    @ConditionalOnMissingBean(AuthenticationFailureHandler.class)
    public RestAuthenticationFailureHandler restAuthenticationFailureHandler() {
        return new RestAuthenticationFailureHandler();
    }

    /**
     * @return 登出成果后的自定义处理（不再由SpringSecurity自动跳转页面）
     */
    @Bean
    @ConditionalOnMissingBean(LogoutSuccessHandler.class)
    public RestLogoutSuccessHandler restLogoutSuccessHandler() {
        return new RestLogoutSuccessHandler();
    }


    @Bean
    @ConditionalOnMissingBean(FieldDataAccessHandler.class)
    public FieldDataAccessHandler getFieldDataAccessHandler() {
        return new FieldDataAccessHandler();
    }

    @Bean
    @ConditionalOnMissingBean(DefaultDataAccessHandler.class)
    public DefaultDataAccessHandler getDataAccessHandlerManager() {
        DefaultDataAccessHandler handler = new DefaultDataAccessHandler();
        return handler;
    }

    @Bean
    @ConditionalOnMissingBean(CreateDepartmentRecordableBeanHandler.class)
    public RecordableBeanHandler createDepartmentRecordableBeanHandler() {
        return new CreateDepartmentRecordableBeanHandler();
    }

    @Bean
    @ConditionalOnMissingBean(CreatorRecordableBeanHandler.class)
    public RecordableBeanHandler creatorRecordableBeanHandler() {
        return new CreatorRecordableBeanHandler();
    }

    @Bean
    @ConditionalOnMissingBean(UpdateDepartmentRecordableBeanHandler.class)
    public RecordableBeanHandler updateDepartmentRecordableBeanHandler() {
        return new UpdateDepartmentRecordableBeanHandler();
    }

    @Bean
    @ConditionalOnMissingBean(UpdaterRecordableBeanHandler.class)
    public RecordableBeanHandler updaterRecordableBeanHandler() {
        return new UpdaterRecordableBeanHandler();
    }

    @Bean
    @ConditionalOnMissingBean(TokenLoginFilter.class)
    public TokenLoginFilter restCheckIsLoginFilter() {
        return new TokenLoginFilter();
    }
}
